<?php
require_once(dirname(__FILE__) . '/../classes/Deferred.php');
require_once(dirname(__FILE__) . '/../classes/DeferredList.php');

/**
 * Make Deferred function retriable
 * @param callback $func
 * @param int $retry
 * @return Deferred 
 */
function createRetryFunction($func, $retry = 0) {
    if(!is_callable($func)) {
        throw new DieException('The contents of a variable can not be called as a function');
    }
    $return = function() use ($func, $retry) {
        $def = new Deferred();
        $data = func_get_args();
        $tmp = call_user_func_array($func, $data);
        $tmp->addCallbacks(function($result) use($def) {
            $def->callback($result);
            return $result;
        }, function($result) use($def) {
            $def->errback($result);
            return $result;
        });
        for($i = 0; $i < $retry; $i++) {
            $def->addErrback(function($result) use($func, $data) {
                $tmp = call_user_func_array($func, $data);
                return $tmp;
            });
        }
        return $def;
    };
    return $return;
}

function createDeferredFunction($func) {
    if(!is_callable($func)) {
        throw new DieException('The contents of a variable can not be called as a function');
    }
    // TODO create class DefferedFunctor, and return him. if $func is DefferedFunctor(Actor ??) - nothing do
    // Fix for cases createDeferredFunction(createDeferredFunction(createDeferredFunction($func)))
    return function ($data) use(&$func) {
        $result = new Deferred();
        $start = new DeferredList(func_get_args());
        $start->addBoth(function($data) use ($result, &$func) {
            //start body
            $q = call_user_func_array($func, $data);
            $result->callback($q);
            //end body
            return $data;
        });
        return $result;
    };
}